package test.demo;

import com.alibaba.fastjson.JSON;
import tech.waterism.modelbase.PredictBase;
import tech.waterism.modelbase.PredictResult;

import java.util.*;

/**
 * 霍顿下渗曲线模型 产流模型
 *
 * @author 潘晓健
 * @version 1.0
 * @date 2022-6-29
 */

public class HORTON extends PredictBase {

    /**
     * 流域平均张力水容量（mm）、流域蓄水容量
     */
    private double Wm;

    /**
     * 流域蒸散发折算系数
     */
    private double Kc;

    /**
     * 流域 月蒸发量（mm）
     */
    private double[] ES;

    /**
     * 流域初始下渗能力，相当于土壤干燥时的下渗能力，平均最大下渗能力，mm/min
     */
    private double f0;

    /**
     * 流域平均稳定下渗能力，mm/min
     */
    private double fc;

    /**
     * 土壤含水计算的允许误差
     */
    private double err_limit;

    /**
     * 下渗能力衰弱系数，随土质而变的系数，1/min
     */
    private double k;

    /**
     * 流域 时段蒸发量（mm）
     */
    private double[] floodE;

    /**
     * 降水时间
     */
    private Date[] floodTm;

    /**
     * 降水量
     */
    private double[] floodDrp;

    /**
     * 降水序列长度
     */
    private Integer floodRainRange;

    /**
     * 降水时段长
     */
    private double timeInterval;

    /**
     * 模拟总产流
     */
    private double[] RunoffSim;

    /**
     * 总产流
     */
    private double[] R;

    /**
     * 净雨
     */
    private double[] PE;

    /**
     * 雨强 mm/min
     */
    private double[] PEI;

    /**
     * 张力水含量
     */
    private double[] Ws;

    /**
     * 下渗能力
     */
    private double[] F;

    /**
     * 流域张力水含量初值（m）
     */
    private double WSInitial;

    public HORTON(Map<String, String> data) {
        super();
        WSInitial = Double.parseDouble(data.get("WSIG"));
        Kc = Double.parseDouble(data.get("KC"));
        err_limit = Double.parseDouble(data.get("ERLMT"));
        k = Double.parseDouble(data.get("K"));
        ES = JSON.parseObject(data.get("ES"), double[].class);
        floodTm = JSON.parseObject(data.get("dt"), Date[].class);// input[i].data.dt
        floodDrp = JSON.parseObject(data.get("rain"), double[].class);// input[i].data.rain
        floodE = JSON.parseObject(data.get("evaporation"), double[].class);  // input[i].data.evaporation
        floodRainRange = floodDrp.length;
        if(floodTm.length > 1){
            timeInterval = getHours(floodTm[0], floodTm[1]);
        }else{
            timeInterval = Double.parseDouble(data.get("clen"));                  // index.clen
        }
        f0 = Double.parseDouble(data.get("F0"));
        fc = Double.parseDouble(data.get("FC"));
        Wm = f0 / k;
        RunoffSim = new double[floodRainRange];
        R = new double[floodRainRange];
        //        RIm = new double[floodRainRange];
        PE = new double[floodRainRange];
        PEI = new double[floodRainRange];
        F =  new double[floodRainRange];
    }

    /**
     * 模型计算
     */
    public Map<String, double[]> HORTONmodel() {

        // 超渗产流
        expinfMechanism();

        for (Integer j = 0; j < floodRainRange; j++) {
            //            RunoffSim[j] = RS[j] + RIm[j] + RI[j] + RG[j];
            RunoffSim[j] = R[j];
        }

        Map<String, double[]> simulationResult = new HashMap<>();
        simulationResult.put("rain", floodDrp);
        simulationResult.put("PE", PE);
        simulationResult.put("runoffSim", RunoffSim);
        simulationResult.put("R", R);
        simulationResult.put("F", F);
        simulationResult.put("PEI", PEI);
        //        simulationResult.put("RIM", RIm);

        return simulationResult;
    }

    /**
     * 蒸发计算
     *
     * @param date   降水时间
     * @param timeIn 时间间隔 (h)
     * @return 蒸发
     */
    private double calcEvaporationPotential(Date date, double timeIn) {
        Calendar time = Calendar.getInstance();
        time.setTime(date);
        Integer Month = time.get(Calendar.MONTH) + 1; // 获得降雨开始月份
        double Ep = ES[Month - 1] / 30; // 月蒸发量转换成日蒸发量
        Ep = Ep * timeIn / 24; // 日蒸发量转换成时段蒸发量
        return Ep;
    }

    /**
     * 超渗产流模型
     *
     * @return 总产流
     */
    private void expinfMechanism() {

        Ws = new double[floodRainRange + 1]; // 张力水蓄量，随时段变化
        Ws[0] = WSInitial;

        double EPt; // EPt为蒸散发，等于Kc * E（实测蒸发，即ES[]或时段）
        double Ft0 = 0.0; //时段初流域下渗能力
        double Ft = 0.0;  //时段下渗量
        double Fw = 0.0;  //时段末流域下渗能力
        double Fg = 0.0;  //时段地下径流入渗率
        double RS = 0.0;  //地表产流
        double RG = 0.0;  //地下产流


        for (Integer i = 0; i < floodRainRange; i++) {

            //蒸发计算
            if (floodE == null || floodE.length != floodRainRange) {
                EPt = Kc * calcEvaporationPotential(floodTm[i], timeInterval);
            } else {
                EPt = Kc * floodE[i];
            }

            // PE[i]为降雨减去蒸发，可正可负
            PE[i] = floodDrp[i];
            PEI[i] = PE[i] / (60 * timeInterval);
            Ft0 = HortonInfilF(Ws[i]);
            F[i] = Ft0;

            if (PEI[i] > Ft0) {
                Ft = Ft0 * 60 * timeInterval;
                Ws[i + 1] = Ws[i] + Ft;
                if(Ft < 0){
                    Ft = 0;
                }
                if(Ws[i + 1] > Wm){
                    Ws[i + 1] = Wm;
                }
                if(Ws[i + 1] < 0){
                    Ws[i + 1] = 0;
                }

                R[i] = PE[i] - Ft;
                if(R[i] < 0){
                    R[i] = 0;
                }
            }else{
                Ft = PE[i];
                R[i] = 0;
                Ws[i + 1] = Ws[i] + Ft;
                if(Ws[i + 1]  > Wm){
                    Ws[i + 1] = Wm;
                }
                if(Ws[i + 1] < 0){
                    Ws[i + 1] = 0;
                }
            }

            /*Ws[i + 1] = (Ws[i] + PE[i] - EPt) / (fc * 60 * timeInterval / Wm + 1);
            if(Ws[i + 1] > Wm){
                Ws[i + 1] = Wm;
            }
            if(Ws[i + 1] < 0){
                Ws[i + 1] = 0;
            }
            Fw = f0 - (f0 - fc) * Ws[i + 1] / Wm;
            if(PEI[i] >= Fw) {
                Ws[i + 1] = (Ws[i] + f0 * 60 * timeInterval - EPt) / (f0 * 60 * timeInterval / Wm + 1);
                if(Ws[i + 1] > Wm){
                    Ws[i + 1] = Wm;
                }
                if(Ws[i + 1] < 0){
                    Ws[i + 1] = 0;
                }
                Fw = f0 - (f0 - fc) * Ws[i + 1] / Wm;
                RS = PE[i] - Fw * 60 * timeInterval - EPt;
            } else {
                RS = 0.0;
            }
            Fg = fc * Ws[i + 1] / Wm;
            if(PEI[i] >= Fg) {
                RG = Fg * 60 * timeInterval;
            } else {
                RG = PE[i];
            }

            R[i] = RG + RS;*/

            // 全流域产流
            /*if (PEI[i] > Ft0) {
                *//*Ws[i + 1] = fc * 60 * timeInterval * (i + 1) + 1 / k * (f0 - fc) * (1 - Math.exp(-k * 60 * timeInterval * (i + 1)));
                if(Ws[i + 1] > Wm){
                    Ws[i + 1] = Wm;
                }
                Ft = Ws[i + 1] - Ws[i];*//*

                Ft = Ft0 * 60 * timeInterval;
                Ws[i + 1] = Ws[i] + Ft;
                if(Ft < 0){
                    Ft = 0;
                }
                if(Ws[i + 1] > Wm){
                    Ws[i + 1] = Wm;
                }
                if(Ws[i + 1] < 0){
                    Ws[i + 1] = 0;
                }

                R[i] = PE[i] - Ft;
                if(R[i] < 0){
                    R[i] = 0;
                }
            }else{
                Ft = PE[i];
                R[i] = 0;
                Ws[i + 1] = Ws[i] + Ft;
                if(Ws[i + 1]  > Wm){
                    Ws[i + 1] = Wm;
                }
                if(Ws[i + 1] < 0){
                    Ws[i + 1] = 0;
                }
            }*/
        }
    }

    /**
     * 霍顿下渗曲线计算
     *
     * @param w0 时段初土壤含水
     * @return 下渗能力
     */
    private double HortonInfilW(double w0) {
        /*
            理论基础：<流域水文模型-新安江模型和陕北模型>pdf66页
            数学基础：迭代求解
        */
        // 由经验初设模型参数
        double T = w0 / f0;

        double w0ByCount = fc * T + 1 / k * (f0 - fc) * (1 - Math.exp(-k * T));
        double fByCount = 0.0;
        while (Math.abs(w0 - w0ByCount) > err_limit) {
            fByCount = f0 - k * (w0ByCount - fc * T);
//            fByCount = fc + (f0 - fc) * Math.exp(-k * T);
            T = T + (w0 - w0ByCount) / fByCount;
            w0ByCount = fc * T + 1 / k * (f0 - fc) * (1 - Math.exp(-k * T));
        }
        fByCount = f0 - k * (w0 - fc * T);
        return fByCount;
    }

    /**
     * 霍顿下渗曲线计算
     *
     * @param w0 时段初土壤含水
     * @return 下渗能力
     */
    private double HortonInfilF(double w0) {
        /*
            理论基础：<基于霍顿下渗公式超渗产流计算几个问题的探讨>
            数学基础：迭代求解
        */
        double f = f0;
        double fByCount = f0 - k * w0 + fc * Math.log10((f0 - fc)/(f - fc));
        if((fByCount - fc) <= (f0 - fc) * Math.exp(-4)) {
            fByCount = fc / 0.62;
        } else if((fByCount - fc) >= (f0 - fc) * Math.exp(-2)) {
            fByCount = fc / 0.92;
        }
        while (Math.abs(f - fByCount) > err_limit && Math.abs(f - fByCount) / f < 2) {
            f = (fByCount + f) / 2;
            fByCount = f0 - k * w0 + fc * Math.log10((f0 - fc)/(f - fc));
        }

        if(Math.abs(f - fByCount) / f >= 2) {
            return f;
        } else {
            return fByCount;
        }
    }

    private List<String> toStringList(double[] array0) {
        String[] array = new String[array0.length];
        for (int i = 0; i < array.length; i++) {
            array[i] = String.valueOf(array0[i]);
        }
        return Arrays.asList(array);
    }

    private List<String> toStringList(double[][] array0) {
        String[] array = new String[array0.length];
        for (int i = 0; i < array.length; i++) {
            array[i] = Arrays.toString(array0[i]);
        }
        return Arrays.asList(array);
    }

    @Override
    public void init() {

    }

    @Override
    public PredictResult predict() {
        PredictResult result = new PredictResult();
        Map<String, double[]> map = HORTONmodel();

        double[][] RSim = new double[3][];
        //总产流
        RSim[0] = map.get("R");
        RSim[1] = map.get("F");
        RSim[2] = map.get("PEI");
        //        //流域地表产流
        //        RSim[1] = map.get("RS");
        //        //流域土壤产流
        //        RSim[2] = map.get("RI");
        //        //流域地下产流
        //        RSim[3] = map.get("RG");

        //流域面积总产流
        result.setRunoffSim(map.get("runoffSim"));

        result.setRSim(RSim);

        // 更新状态
        List<String> WS = toStringList(Ws);
        //        List<String> WUP = toStringList(Wu);
        //        List<String> WLP = toStringList(Wl);
        //        List<String> WDP = toStringList(Wd);
        //        List<String> SP = toStringList(S);
        //        List<String> FRP = toStringList(FR);
        //        List<String> QXSIG = toStringList(QX0);
        //        List<String> QSIG = toStringList(QS0);
        //        List<String> QSP = toStringList(QS);
        //        List<String> QIP = toStringList(QIS0);
        //        List<String> QGP = toStringList(QGS0);
        //        List<String> QSP = toStringList(QS);
        //        List<String> QIP = toStringList(QI);
        //        List<String> QGP = toStringList(QG);
        Map<String, List<String>> status = new HashMap<>();
        //土壤含水量
        status.put("WS", WS);
        //        //上层张力水含量
        //        status.put("WUP", WUP);
        //        //下层张力水含量
        //        status.put("WLP", WLP);
        //        //深层张力水含量
        //        status.put("WDP", WDP);
        //        //产流面积自由水深
        //        status.put("SP", SP);
        //        //产流面积系数
        //        status.put("FRP", FRP);
        //        //河段下断面各时段初始流量
        //        status.put("QXSIG", QXSIG);
        //        //各时段初始总基流
        //        status.put("QSIG", QSIG);
        //        //地表坡面汇流
        //        status.put("QSP", QSP);
        //        //坡面汇流-壤中流
        //        status.put("QIP", QIP);
        //        //地下坡面汇流
        //        status.put("QGP", QGP);
        result.setNewStatus(status);

        return result;

        //return null;
    }

    private int getHours(Date dt_beg, Date dt_end) {
        int hours = -1;
        hours = Long.valueOf((dt_end.getTime() - dt_beg.getTime()) / (3600 * 1000L)).intValue();
        return hours;
    }

    public static void main(String[] args) {
        String a = "{\"K\":\"0.041\",\"dt\":\"[\\\"2020-05-31 08:00:00\\\",\\\"2020-05-31 14:00:00\\\",\\\"2020-05-31 20:00:00\\\",\\\"2020-06-01 02:00:00\\\",\\\"2020-06-01 08:00:00\\\",\\\"2020-06-01 14:00:00\\\",\\\"2020-06-01 20:00:00\\\",\\\"2020-06-02 02:00:00\\\",\\\"2020-06-02 08:00:00\\\",\\\"2020-06-02 14:00:00\\\",\\\"2020-06-02 20:00:00\\\",\\\"2020-06-03 02:00:00\\\",\\\"2020-06-03 08:00:00\\\",\\\"2020-06-03 14:00:00\\\",\\\"2020-06-03 20:00:00\\\",\\\"2020-06-04 02:00:00\\\",\\\"2020-06-04 08:00:00\\\",\\\"2020-06-04 14:00:00\\\",\\\"2020-06-04 20:00:00\\\",\\\"2020-06-05 02:00:00\\\",\\\"2020-06-05 08:00:00\\\",\\\"2020-06-05 14:00:00\\\",\\\"2020-06-05 20:00:00\\\",\\\"2020-06-06 02:00:00\\\",\\\"2020-06-06 08:00:00\\\",\\\"2020-06-06 14:00:00\\\",\\\"2020-06-06 20:00:00\\\",\\\"2020-06-07 02:00:00\\\",\\\"2020-06-07 08:00:00\\\",\\\"2020-06-07 14:00:00\\\",\\\"2020-06-07 20:00:00\\\",\\\"2020-06-08 02:00:00\\\",\\\"2020-06-08 08:00:00\\\",\\\"2020-06-08 14:00:00\\\",\\\"2020-06-08 20:00:00\\\",\\\"2020-06-09 02:00:00\\\",\\\"2020-06-09 08:00:00\\\",\\\"2020-06-09 14:00:00\\\",\\\"2020-06-09 20:00:00\\\",\\\"2020-06-10 02:00:00\\\",\\\"2020-06-10 08:00:00\\\",\\\"2020-06-10 14:00:00\\\",\\\"2020-06-10 20:00:00\\\",\\\"2020-06-11 02:00:00\\\",\\\"2020-06-11 08:00:00\\\",\\\"2020-06-11 14:00:00\\\",\\\"2020-06-11 20:00:00\\\",\\\"2020-06-12 02:00:00\\\",\\\"2020-06-12 08:00:00\\\",\\\"2020-06-12 14:00:00\\\",\\\"2020-06-12 20:00:00\\\",\\\"2020-06-13 02:00:00\\\",\\\"2020-06-13 08:00:00\\\",\\\"2020-06-13 14:00:00\\\",\\\"2020-06-13 20:00:00\\\",\\\"2020-06-14 02:00:00\\\",\\\"2020-06-14 08:00:00\\\",\\\"2020-06-14 14:00:00\\\",\\\"2020-06-14 20:00:00\\\",\\\"2020-06-15 02:00:00\\\",\\\"2020-06-15 08:00:00\\\",\\\"2020-06-15 14:00:00\\\",\\\"2020-06-15 20:00:00\\\",\\\"2020-06-16 02:00:00\\\",\\\"2020-06-16 08:00:00\\\",\\\"2020-06-16 14:00:00\\\",\\\"2020-06-16 20:00:00\\\",\\\"2020-06-17 02:00:00\\\",\\\"2020-06-17 08:00:00\\\",\\\"2020-06-17 14:00:00\\\",\\\"2020-06-17 20:00:00\\\",\\\"2020-06-18 02:00:00\\\",\\\"2020-06-18 08:00:00\\\",\\\"2020-06-18 14:00:00\\\",\\\"2020-06-18 20:00:00\\\",\\\"2020-06-19 02:00:00\\\",\\\"2020-06-19 08:00:00\\\",\\\"2020-06-19 14:00:00\\\",\\\"2020-06-19 20:00:00\\\",\\\"2020-06-20 02:00:00\\\",\\\"2020-06-20 08:00:00\\\",\\\"2020-06-20 14:00:00\\\",\\\"2020-06-20 20:00:00\\\",\\\"2020-06-21 02:00:00\\\",\\\"2020-06-21 08:00:00\\\",\\\"2020-06-21 14:00:00\\\",\\\"2020-06-21 20:00:00\\\",\\\"2020-06-22 02:00:00\\\",\\\"2020-06-22 08:00:00\\\",\\\"2020-06-22 14:00:00\\\",\\\"2020-06-22 20:00:00\\\",\\\"2020-06-23 02:00:00\\\",\\\"2020-06-23 08:00:00\\\",\\\"2020-06-23 14:00:00\\\",\\\"2020-06-23 20:00:00\\\",\\\"2020-06-24 02:00:00\\\",\\\"2020-06-24 08:00:00\\\",\\\"2020-06-24 14:00:00\\\",\\\"2020-06-24 20:00:00\\\",\\\"2020-06-25 02:00:00\\\",\\\"2020-06-25 08:00:00\\\",\\\"2020-06-25 14:00:00\\\",\\\"2020-06-25 20:00:00\\\",\\\"2020-06-26 02:00:00\\\",\\\"2020-06-26 08:00:00\\\",\\\"2020-06-26 14:00:00\\\",\\\"2020-06-26 20:00:00\\\",\\\"2020-06-27 02:00:00\\\",\\\"2020-06-27 08:00:00\\\",\\\"2020-06-27 14:00:00\\\",\\\"2020-06-27 20:00:00\\\",\\\"2020-06-28 02:00:00\\\",\\\"2020-06-28 08:00:00\\\",\\\"2020-06-28 14:00:00\\\",\\\"2020-06-28 20:00:00\\\",\\\"2020-06-29 02:00:00\\\",\\\"2020-06-29 08:00:00\\\",\\\"2020-06-29 14:00:00\\\",\\\"2020-06-29 20:00:00\\\",\\\"2020-06-30 02:00:00\\\",\\\"2020-06-30 08:00:00\\\",\\\"2020-06-30 14:00:00\\\",\\\"2020-06-30 20:00:00\\\",\\\"2020-07-01 02:00:00\\\",\\\"2020-07-01 08:00:00\\\",\\\"2020-07-01 14:00:00\\\",\\\"2020-07-01 20:00:00\\\",\\\"2020-07-02 02:00:00\\\",\\\"2020-07-02 08:00:00\\\",\\\"2020-07-02 14:00:00\\\",\\\"2020-07-02 20:00:00\\\",\\\"2020-07-03 02:00:00\\\",\\\"2020-07-03 08:00:00\\\",\\\"2020-07-03 14:00:00\\\",\\\"2020-07-03 20:00:00\\\",\\\"2020-07-04 02:00:00\\\",\\\"2020-07-04 08:00:00\\\",\\\"2020-07-04 14:00:00\\\",\\\"2020-07-04 20:00:00\\\",\\\"2020-07-05 02:00:00\\\",\\\"2020-07-05 08:00:00\\\",\\\"2020-07-05 14:00:00\\\",\\\"2020-07-05 20:00:00\\\",\\\"2020-07-06 02:00:00\\\",\\\"2020-07-06 08:00:00\\\",\\\"2020-07-06 14:00:00\\\",\\\"2020-07-06 20:00:00\\\",\\\"2020-07-07 02:00:00\\\",\\\"2020-07-07 08:00:00\\\",\\\"2020-07-07 14:00:00\\\",\\\"2020-07-07 20:00:00\\\",\\\"2020-07-08 02:00:00\\\",\\\"2020-07-08 08:00:00\\\",\\\"2020-07-08 14:00:00\\\",\\\"2020-07-08 20:00:00\\\",\\\"2020-07-09 02:00:00\\\",\\\"2020-07-09 08:00:00\\\",\\\"2020-07-09 14:00:00\\\",\\\"2020-07-09 20:00:00\\\",\\\"2020-07-10 02:00:00\\\",\\\"2020-07-10 08:00:00\\\",\\\"2020-07-10 14:00:00\\\",\\\"2020-07-10 20:00:00\\\",\\\"2020-07-11 02:00:00\\\",\\\"2020-07-11 08:00:00\\\",\\\"2020-07-11 14:00:00\\\",\\\"2020-07-11 20:00:00\\\",\\\"2020-07-12 02:00:00\\\",\\\"2020-07-12 08:00:00\\\",\\\"2020-07-12 14:00:00\\\",\\\"2020-07-12 20:00:00\\\",\\\"2020-07-13 02:00:00\\\",\\\"2020-07-13 08:00:00\\\",\\\"2020-07-13 14:00:00\\\",\\\"2020-07-13 20:00:00\\\",\\\"2020-07-14 02:00:00\\\",\\\"2020-07-14 08:00:00\\\",\\\"2020-07-14 14:00:00\\\",\\\"2020-07-14 20:00:00\\\",\\\"2020-07-15 02:00:00\\\",\\\"2020-07-15 08:00:00\\\",\\\"2020-07-15 14:00:00\\\",\\\"2020-07-15 20:00:00\\\",\\\"2020-07-16 02:00:00\\\",\\\"2020-07-16 08:00:00\\\",\\\"2020-07-16 14:00:00\\\",\\\"2020-07-16 20:00:00\\\",\\\"2020-07-17 02:00:00\\\",\\\"2020-07-17 08:00:00\\\",\\\"2020-07-17 14:00:00\\\",\\\"2020-07-17 20:00:00\\\",\\\"2020-07-18 02:00:00\\\",\\\"2020-07-18 08:00:00\\\",\\\"2020-07-18 14:00:00\\\",\\\"2020-07-18 20:00:00\\\",\\\"2020-07-19 02:00:00\\\",\\\"2020-07-19 08:00:00\\\",\\\"2020-07-19 14:00:00\\\",\\\"2020-07-19 20:00:00\\\",\\\"2020-07-20 02:00:00\\\",\\\"2020-07-20 08:00:00\\\",\\\"2020-07-20 14:00:00\\\",\\\"2020-07-20 20:00:00\\\",\\\"2020-07-21 02:00:00\\\",\\\"2020-07-21 08:00:00\\\",\\\"2020-07-21 14:00:00\\\",\\\"2020-07-21 20:00:00\\\",\\\"2020-07-22 02:00:00\\\",\\\"2020-07-22 08:00:00\\\",\\\"2020-07-22 14:00:00\\\",\\\"2020-07-22 20:00:00\\\",\\\"2020-07-23 02:00:00\\\",\\\"2020-07-23 08:00:00\\\",\\\"2020-07-23 14:00:00\\\",\\\"2020-07-23 20:00:00\\\",\\\"2020-07-24 02:00:00\\\",\\\"2020-07-24 08:00:00\\\",\\\"2020-07-24 14:00:00\\\",\\\"2020-07-24 20:00:00\\\",\\\"2020-07-25 02:00:00\\\",\\\"2020-07-25 08:00:00\\\",\\\"2020-07-25 14:00:00\\\",\\\"2020-07-25 20:00:00\\\",\\\"2020-07-26 02:00:00\\\",\\\"2020-07-26 08:00:00\\\",\\\"2020-07-26 14:00:00\\\",\\\"2020-07-26 20:00:00\\\",\\\"2020-07-27 02:00:00\\\",\\\"2020-07-27 08:00:00\\\",\\\"2020-07-27 14:00:00\\\",\\\"2020-07-27 20:00:00\\\",\\\"2020-07-28 02:00:00\\\",\\\"2020-07-28 08:00:00\\\",\\\"2020-07-28 14:00:00\\\",\\\"2020-07-28 20:00:00\\\",\\\"2020-07-29 02:00:00\\\",\\\"2020-07-29 08:00:00\\\",\\\"2020-07-29 14:00:00\\\",\\\"2020-07-29 20:00:00\\\",\\\"2020-07-30 02:00:00\\\",\\\"2020-07-30 08:00:00\\\",\\\"2020-07-30 14:00:00\\\",\\\"2020-07-30 20:00:00\\\",\\\"2020-07-31 02:00:00\\\",\\\"2020-07-31 08:00:00\\\",\\\"2020-07-31 14:00:00\\\",\\\"2020-07-31 20:00:00\\\",\\\"2020-08-01 02:00:00\\\",\\\"2020-08-01 08:00:00\\\",\\\"2020-08-01 14:00:00\\\",\\\"2020-08-01 20:00:00\\\",\\\"2020-08-02 02:00:00\\\",\\\"2020-08-02 08:00:00\\\",\\\"2020-08-02 14:00:00\\\",\\\"2020-08-02 20:00:00\\\",\\\"2020-08-03 02:00:00\\\",\\\"2020-08-03 08:00:00\\\",\\\"2020-08-03 14:00:00\\\",\\\"2020-08-03 20:00:00\\\",\\\"2020-08-04 02:00:00\\\",\\\"2020-08-04 08:00:00\\\",\\\"2020-08-04 14:00:00\\\",\\\"2020-08-04 20:00:00\\\",\\\"2020-08-05 02:00:00\\\",\\\"2020-08-05 08:00:00\\\",\\\"2020-08-05 14:00:00\\\",\\\"2020-08-05 20:00:00\\\",\\\"2020-08-06 02:00:00\\\",\\\"2020-08-06 08:00:00\\\",\\\"2020-08-06 14:00:00\\\",\\\"2020-08-06 20:00:00\\\",\\\"2020-08-07 02:00:00\\\",\\\"2020-08-07 08:00:00\\\",\\\"2020-08-07 14:00:00\\\",\\\"2020-08-07 20:00:00\\\",\\\"2020-08-08 02:00:00\\\",\\\"2020-08-08 08:00:00\\\",\\\"2020-08-08 14:00:00\\\",\\\"2020-08-08 20:00:00\\\",\\\"2020-08-09 02:00:00\\\",\\\"2020-08-09 08:00:00\\\",\\\"2020-08-09 14:00:00\\\",\\\"2020-08-09 20:00:00\\\",\\\"2020-08-10 02:00:00\\\",\\\"2020-08-10 08:00:00\\\",\\\"2020-08-10 14:00:00\\\",\\\"2020-08-10 20:00:00\\\",\\\"2020-08-11 02:00:00\\\",\\\"2020-08-11 08:00:00\\\",\\\"2020-08-11 14:00:00\\\",\\\"2020-08-11 20:00:00\\\",\\\"2020-08-12 02:00:00\\\",\\\"2020-08-12 08:00:00\\\",\\\"2020-08-12 14:00:00\\\",\\\"2020-08-12 20:00:00\\\",\\\"2020-08-13 02:00:00\\\",\\\"2020-08-13 08:00:00\\\",\\\"2020-08-13 14:00:00\\\",\\\"2020-08-13 20:00:00\\\",\\\"2020-08-14 02:00:00\\\",\\\"2020-08-14 08:00:00\\\",\\\"2020-08-14 14:00:00\\\",\\\"2020-08-14 20:00:00\\\",\\\"2020-08-15 02:00:00\\\",\\\"2020-08-15 08:00:00\\\",\\\"2020-08-15 14:00:00\\\",\\\"2020-08-15 20:00:00\\\",\\\"2020-08-16 02:00:00\\\",\\\"2020-08-16 08:00:00\\\",\\\"2020-08-16 14:00:00\\\",\\\"2020-08-16 20:00:00\\\",\\\"2020-08-17 02:00:00\\\",\\\"2020-08-17 08:00:00\\\",\\\"2020-08-17 14:00:00\\\",\\\"2020-08-17 20:00:00\\\",\\\"2020-08-18 02:00:00\\\",\\\"2020-08-18 08:00:00\\\",\\\"2020-08-18 14:00:00\\\",\\\"2020-08-18 20:00:00\\\",\\\"2020-08-19 02:00:00\\\",\\\"2020-08-19 08:00:00\\\",\\\"2020-08-19 14:00:00\\\",\\\"2020-08-19 20:00:00\\\",\\\"2020-08-20 02:00:00\\\",\\\"2020-08-20 08:00:00\\\",\\\"2020-08-20 14:00:00\\\",\\\"2020-08-20 20:00:00\\\",\\\"2020-08-21 02:00:00\\\",\\\"2020-08-21 08:00:00\\\",\\\"2020-08-21 14:00:00\\\",\\\"2020-08-21 20:00:00\\\",\\\"2020-08-22 02:00:00\\\",\\\"2020-08-22 08:00:00\\\",\\\"2020-08-22 14:00:00\\\",\\\"2020-08-22 20:00:00\\\",\\\"2020-08-23 02:00:00\\\",\\\"2020-08-23 08:00:00\\\",\\\"2020-08-23 14:00:00\\\",\\\"2020-08-23 20:00:00\\\",\\\"2020-08-24 02:00:00\\\",\\\"2020-08-24 08:00:00\\\",\\\"2020-08-24 14:00:00\\\",\\\"2020-08-24 20:00:00\\\",\\\"2020-08-25 02:00:00\\\",\\\"2020-08-25 08:00:00\\\",\\\"2020-08-25 14:00:00\\\",\\\"2020-08-25 20:00:00\\\",\\\"2020-08-26 02:00:00\\\",\\\"2020-08-26 08:00:00\\\",\\\"2020-08-26 14:00:00\\\",\\\"2020-08-26 20:00:00\\\",\\\"2020-08-27 02:00:00\\\",\\\"2020-08-27 08:00:00\\\",\\\"2020-08-27 14:00:00\\\",\\\"2020-08-27 20:00:00\\\",\\\"2020-08-28 02:00:00\\\",\\\"2020-08-28 08:00:00\\\",\\\"2020-08-28 14:00:00\\\",\\\"2020-08-28 20:00:00\\\",\\\"2020-08-29 02:00:00\\\",\\\"2020-08-29 08:00:00\\\"]\",\"WSIG\":\"0.0\",\"ERLMT\":\"0.2\",\"KC\":\"0.84\",\"rain\":\"[0.22628205128205134,4.708974382051281,7.614102505128206,2.406410276923076,0.5166666666666668,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.010256410256410256,0.5589743615384615,1.3664283846153845E-17,1.3664283846153845E-17,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.005128205128205128,0.016025641025641024,0.016025641025641024,0.016025641025641024,0.5826923076923076,1.0371794769230767,0.632051282051282,0.03205128205128205,0.6269230769230769,1.954678654615384,4.053213448717948,0.13964369015384617,0.17041292092307694,0.01282051282051282,0.0,0.0,0.01282051282051282,0.0,0.0,0.0,0.005128205128205128,0.026282051282051314,3.9775641358974365,0.03910256410256413,0.06987179487179489,0.015384615384615385,0.0,0.020512820512820513,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.023717948717948717,0.023717948717948717,0.0391025641025641,0.023717948717948717,0.08012820512820512,0.08012820512820512,2.1365384717948714,0.13653846153846155,0.0,0.0,0.0,0.11282051538461535,3.7493589666666676,3.023717948717948,1.6621794358974358,0.38525641025641033,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.005128205128205128,0.0,0.005128205128205128,0.0,0.0,0.0,0.002564102564102564,0.022435897435897436,0.10705128205128205,0.027564102564102563,0.025,0.0,0.0,0.0,0.005128205128205128,0.0,0.0,0.0,0.005128205128205128,0.0,0.038461538461538464,0.002564102564102564,0.007692307692307692,0.10740563846153849,3.4102139307692303,0.11600042564102563,0.10740563846153849,0.07307692307692307,0.2705128307692307,0.17051282307692303,0.07564102564102564,0.8249999761538465,43.05320479487179,7.753205132564103,0.33012820692307726,0.050641025641025635,1.4839743589743588,0.3096153846153846,0.06858974358974358,0.010256410256410256,0.0,0.005128205128205128,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.06474358974358974,0.06474358974358974,0.06474358974358974,0.06474358974358974,0.0,0.4615384615384615,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.009615384615384616,0.009615384615384616,0.2762820512820513,0.2711538461538462,0.04358974358974359,0.01282051282051282,0.002564102564102564,0.002564102564102564,0.0,0.0,0.0,0.0,0.0,0.02564102564102564,0.0,0.0,0.35384615384615387,0.046153846153846156,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.015384615384615384,0.09230769230769231,0.0,0.16923076923076924,0.04358974358974359,0.0641025641025641,0.0,0.0,0.11538461538461538,0.10256410256410256,0.0,1.574358974358974,5.880641017948719,0.9493589743589744,10.04474363333333,0.8688461533333331,0.010256410256410256,0.005128205128205128,0.0,0.0,0.49287545538461536,18.803937728205128,3.4626190553846143,0.3610805861538461,0.017948717948717947,0.4923076923076923,0.0,0.0,0.005128205128205128,0.0,0.3205128205128206,0.03333333333333333,1.1673076923076922,5.223717976923076,0.11602564102564104,0.11089743589743595,0.005128205128205128,0.0,0.0,0.0,0.0,0.020512820512820513,0.0,0.0,0.0,0.0,0.0,0.0,0.005128205128205128,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.5256410256410257,0.0,0.0,0.003205128205128205,0.003205128205128205,0.008333333333333333,0.1032051282051282,0.0,0.0,0.0,0.0,0.20213675282051283,0.6303418810256409,1.1414529974358971,3.8491453256410253,5.880442891025641,0.26044289094871803,0.23212121171794878,0.27571095530769235,0.005128205128205128,0.0,0.0,0.0,0.0,0.24358974358974358,0.05128205128205128,0.005128205128205128,0.11474358974358977,0.11474358974358977,0.11474358974358977,3.6198717999999994,4.239993310256409,0.2806859794871795,0.14991674871794877,0.1550449538461539,1.8108669146153846,9.751587184615383,4.380525015384615,1.018559222307692,0.05128205128205129,0.14615384615384616,0.01282051282051282,0.0,0.01282051282051282,0.005128205128205128,0.0,0.005128205128205128,0.0,0.1282051282051282,0.0,0.010256410256410256,0.005128205128205128,0.0,0.0,0.002564102564102564,0.515688258974359,0.515688258974359,1.0417566358974357,14.931995166666667,9.302732843589748,0.3426788141025641,0.32985830128205135,0.3811403525641025,0.0,0.005128205128205128,0.0,0.0,0.18453666153846154,0.18966486666666668,0.7832321230769228,6.429745943589742,11.533333294871797,1.8521870512820509,0.8328808474358972,0.7149321294871793,0.049358974358974364,0.010897435897435897,0.016025641025641024,0.010897435897435897]\",\"MP\":\"20\",\"IM\":\"0.029827238885660367\",\"QSIG\":\"[0.000, 0.000]\",\"start\":\"\\\"2020-06-30 08:00:00\\\"\",\"F0\":\"1.22\",\"ES\":\"[23.8, 23.2, 33.7, 53, 66.6, 78.9, 122.3, 113.9, 90.8, 62.9, 46.2, 34.1]\",\"QSP\":\"0.000\",\"CS\":\"0.8968975627059064\",\"q\":\"[]\",\"LAG\":\"19.75125860965323\",\"QXSIG\":\"[0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000]\",\"runoffSim\":\"[]\",\"clen\":\"6\",\"FC\":\"0.0472\"}";
        Map data = JSON.parseObject(a, Map.class);
        HORTON obj = new HORTON(data);
        System.out.println(obj.predict());
    }
}
